from typing import Literal, List, Union
from enum import Enum

from game.item import Item, ItemType

# TODO: Should we use Enum here?
class Slot(Enum):
    helmet = 0
    chestplate = 1
    leggings = 2
    boots = 3
    
    hotbar0 = 4
    hotbar1 = 5
    hotbar2 = 6
    hotbar3 = 7
    hotbar4 = 8
    hotbar5 = 9
    hotbar6 = 10
    hotbar7 = 11
    hotbar8 = 12

class Inventory:
    
    def __init__(self):
        self.holdingSlot: Slot = Slot.hotbar0
        
        self.slots: List[Union[Item, None]] = [None] * 12
    
    
    def __getitem__(self, __slot: Slot) -> Union[Item, None]:
        return self.slots[__slot.value]
    
    def __setitem__(self, __slot: Slot, __item: Item) -> None:
        original_item = self.slots[__slot.value]
        self.slots[__slot.value] = __item
        
        if original_item is not None:
            self.obtainItem(original_item)
    
    @property
    def holdingItem(self) -> Union[Item, None]:
        return self.__getitem__(self.holdingSlot)
    
    @property
    def is_hotbar_full(self) -> bool:
        for slot in HOTBAR_SLOTS:
            if self.__getitem__(slot) is None:
                return False
        return True
    
    def obtainItem(self, item: Item):
        # TODO: Add mechanics when hotbar is full
        for slot in HOTBAR_SLOTS:
            if self.__getitem__(slot) is None:
                self.__setitem__(slot, item)
                return
    
    def equip_armor(self, item: Item, armor_type: Literal[ItemType.helmet, ItemType.chestplate, ItemType.leggings, ItemType.boots]) -> None:
        if armor_type == ItemType.helmet:
            assert item.type == ItemType.helmet
            self.__setitem__(Slot.helmet, item)
        
        elif armor_type == ItemType.chestplate:
            assert item.type == ItemType.chestplate
            self.__setitem__(Slot.chestplate, item)
            
        elif armor_type == ItemType.leggings:
            assert item.type == ItemType.leggings
            self.__setitem__(Slot.leggings, item)
            
        elif armor_type == ItemType.boots:
            assert item.type == ItemType.boots
            self.__setitem__(Slot.boots, item)
            
        else:
            # TODO: Maybe add type_checking? So we don't need to raise Exception here
            raise TypeError()
        
HOTBAR_SLOTS = [Slot.hotbar0, Slot.hotbar1, Slot.hotbar2, Slot.hotbar3, Slot.hotbar4,
           Slot.hotbar5, Slot.hotbar6, Slot.hotbar7, Slot.hotbar8]